/*
  WPA2-ENT EAP-TLS
  based on joostd's code : https://github.com/joostd/esp8266-eduroam
  https://github.com/joostd/esp8266-eduroam/blob/master/gen_cert.sh


  wifi_station_set_cert_key
  Function: Set certificate and private key for connecting to WPA2-ENTERPRISE AP.
  Note:
  • Connecting to WPA2-ENTERPRISE AP needs more than 26 KB memory, please ensure enough space (system_get_free_heap_size). ---> 보통 45K 남아 있음
  •  So far, WPA2-ENTERPRISE can only support unencrypted certificate and private key, and only in PEM format.
        ‣ Header of certificate: - - - - - BEGIN CERTIFICATE - - - - -
        ‣ Headerofprivatekey:-----BEGINRSAPRIVATEKEY-----
             or - - - - - BEGIN PRIVATE KEY - - - - -
  •  Please call this API to set certificate and private key before connecting to WPA2-ENTERPRISE AP and the application needs to hold the certificate and private key. Call wifi_station_clear_cert_key to release resources and clear status after connected to the target AP, and then the application can release the certificate and private key.
  •  If the private key is encrypted, please use openssl pkey command to change it to unencrypted file to use, or use openssl rsa related commands to change it (or change the start TAG).

  Prototype:
        bool wifi_station_set_cert_key (
                uint8 *client_cert,
                int client_cert_len,
                uint8 *private_key,
                int private_key_len,
                uint8 *private_key_passwd,
                int private_key_passwd_len,
        )

  Parameter:
        uint8 *client_cert : certificate, HEX array
        int client_cert_len : length of certificate
        uint8 *private_key : private key, HEX array
        int private_key_len : length of private key
        uint8 *private_key_passwd : password for private key, to be supported, can only be NULL now.
        int private_key_passwd_len : length of password, to be supported, can only be 0 now.

  Return:
        0 : succeed   non-0 : fail

  Example:
  For example, the private key is - - - - - BEGIN PRIVATE KEY - - - - - ... ... ... ...
  Then then array should be uint8 key[]={0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, ... ... 0x00 };
  It is the ASCII of the characters, and the array needs to be ended by 0x00.
*/



// by chaeplin 2016/01/20
// https://github.com/chaeplin/esp8266_and_arduino
/*
  SERVER : Rpi2(freeradius:EAP-TLS, mosquitto:tls1.1)
  AP : DIR-868L(DD-WRT)
  FreeHeap : 16.7K
*/


#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

extern "C" {
#include "user_interface.h"
}

#include "/usr/local/src/ap_setting.h"

#define DEBUG_PRINT 1

#define MQTT_TEST_SERVER { 192, 168, 10, 144 }
#define MQTT_TEST_USER "test1"
#define MQTT_TEST_PASS "test123"

// test
// 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x42, --> can't connect
//
// todo : use flash to store crt and key
uint8 espclient1_crt[] = {
  0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43,
  0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
  0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x44, 0x51, 0x6a, 0x43, 0x43,
  0x41, 0x69, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42,
  0x42, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47,
  0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x41, 0x59,
  0x4d, 0x52, 0x59, 0x77, 0x46, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44,
  0x44, 0x41, 0x31, 0x74, 0x63, 0x58, 0x52, 0x30, 0x0a, 0x63, 0x32, 0x56,
  0x79, 0x64, 0x6d, 0x56, 0x79, 0x49, 0x45, 0x4e, 0x42, 0x4d, 0x42, 0x34,
  0x58, 0x44, 0x54, 0x45, 0x32, 0x4d, 0x44, 0x45, 0x78, 0x4f, 0x54, 0x45,
  0x35, 0x4d, 0x7a, 0x6b, 0x78, 0x4f, 0x46, 0x6f, 0x58, 0x44, 0x54, 0x49,
  0x32, 0x4d, 0x44, 0x45, 0x78, 0x4e, 0x6a, 0x45, 0x35, 0x4d, 0x7a, 0x6b,
  0x78, 0x4f, 0x46, 0x6f, 0x77, 0x46, 0x54, 0x45, 0x54, 0x4d, 0x42, 0x45,
  0x47, 0x0a, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x4b, 0x5a, 0x58,
  0x4e, 0x77, 0x59, 0x32, 0x78, 0x70, 0x5a, 0x57, 0x35, 0x30, 0x4d, 0x54,
  0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f,
  0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51,
  0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41, 0x44, 0x43, 0x43, 0x41, 0x51,
  0x6f, 0x43, 0x67, 0x67, 0x45, 0x42, 0x0a, 0x41, 0x4f, 0x64, 0x39, 0x48,
  0x63, 0x4d, 0x32, 0x53, 0x73, 0x36, 0x4c, 0x4b, 0x2b, 0x68, 0x41, 0x34,
  0x4f, 0x4d, 0x43, 0x66, 0x47, 0x6d, 0x42, 0x68, 0x48, 0x57, 0x73, 0x71,
  0x59, 0x73, 0x4b, 0x6e, 0x2f, 0x30, 0x45, 0x36, 0x79, 0x64, 0x43, 0x4c,
  0x43, 0x78, 0x47, 0x57, 0x70, 0x72, 0x58, 0x76, 0x64, 0x78, 0x38, 0x4a,
  0x42, 0x31, 0x53, 0x50, 0x35, 0x34, 0x67, 0x55, 0x30, 0x57, 0x47, 0x0a,
  0x74, 0x4a, 0x39, 0x2f, 0x37, 0x57, 0x41, 0x75, 0x46, 0x77, 0x35, 0x66,
  0x56, 0x51, 0x61, 0x7a, 0x2f, 0x47, 0x48, 0x48, 0x4a, 0x4e, 0x6a, 0x63,
  0x2b, 0x44, 0x64, 0x44, 0x4c, 0x43, 0x63, 0x67, 0x4d, 0x46, 0x72, 0x72,
  0x31, 0x33, 0x37, 0x69, 0x7a, 0x78, 0x66, 0x41, 0x7a, 0x44, 0x43, 0x46,
  0x2b, 0x76, 0x34, 0x65, 0x53, 0x78, 0x4d, 0x42, 0x42, 0x4a, 0x42, 0x50,
  0x70, 0x36, 0x6c, 0x5a, 0x0a, 0x33, 0x43, 0x48, 0x64, 0x47, 0x46, 0x58,
  0x2f, 0x66, 0x30, 0x42, 0x6f, 0x6c, 0x34, 0x72, 0x32, 0x73, 0x78, 0x39,
  0x75, 0x6d, 0x71, 0x31, 0x68, 0x70, 0x49, 0x47, 0x63, 0x49, 0x38, 0x50,
  0x69, 0x4a, 0x52, 0x54, 0x46, 0x66, 0x69, 0x55, 0x76, 0x35, 0x6e, 0x62,
  0x6f, 0x53, 0x70, 0x59, 0x77, 0x57, 0x4b, 0x45, 0x55, 0x64, 0x67, 0x65,
  0x4e, 0x52, 0x56, 0x45, 0x30, 0x46, 0x64, 0x45, 0x61, 0x0a, 0x33, 0x4b,
  0x41, 0x62, 0x32, 0x4e, 0x7a, 0x64, 0x32, 0x6f, 0x6f, 0x2b, 0x2b, 0x55,
  0x34, 0x4f, 0x37, 0x4b, 0x53, 0x69, 0x53, 0x35, 0x57, 0x36, 0x62, 0x67,
  0x50, 0x6e, 0x7a, 0x48, 0x4d, 0x64, 0x64, 0x64, 0x54, 0x4d, 0x38, 0x57,
  0x64, 0x64, 0x39, 0x7a, 0x35, 0x51, 0x6d, 0x43, 0x2b, 0x39, 0x5a, 0x5a,
  0x49, 0x38, 0x57, 0x65, 0x42, 0x35, 0x45, 0x33, 0x61, 0x44, 0x52, 0x59,
  0x4c, 0x67, 0x0a, 0x2b, 0x39, 0x48, 0x33, 0x64, 0x53, 0x44, 0x34, 0x59,
  0x48, 0x72, 0x49, 0x48, 0x79, 0x4c, 0x4b, 0x6f, 0x39, 0x71, 0x52, 0x68,
  0x6d, 0x63, 0x2b, 0x70, 0x54, 0x4a, 0x6d, 0x33, 0x43, 0x56, 0x54, 0x70,
  0x64, 0x66, 0x2f, 0x52, 0x48, 0x6b, 0x36, 0x67, 0x6b, 0x30, 0x69, 0x6c,
  0x43, 0x53, 0x2b, 0x51, 0x77, 0x56, 0x51, 0x31, 0x58, 0x45, 0x69, 0x45,
  0x68, 0x73, 0x7a, 0x30, 0x32, 0x44, 0x6f, 0x0a, 0x4a, 0x77, 0x65, 0x4a,
  0x2b, 0x71, 0x54, 0x79, 0x75, 0x46, 0x71, 0x33, 0x55, 0x34, 0x45, 0x64,
  0x33, 0x5a, 0x5a, 0x50, 0x76, 0x61, 0x63, 0x43, 0x41, 0x77, 0x45, 0x41,
  0x41, 0x61, 0x4f, 0x42, 0x6d, 0x54, 0x43, 0x42, 0x6c, 0x6a, 0x41, 0x4a,
  0x42, 0x67, 0x4e, 0x56, 0x48, 0x52, 0x4d, 0x45, 0x41, 0x6a, 0x41, 0x41,
  0x4d, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57,
  0x0a, 0x42, 0x42, 0x52, 0x76, 0x39, 0x51, 0x75, 0x37, 0x32, 0x76, 0x50,
  0x71, 0x42, 0x78, 0x41, 0x35, 0x5a, 0x42, 0x57, 0x2b, 0x78, 0x77, 0x34,
  0x56, 0x50, 0x43, 0x57, 0x30, 0x49, 0x6a, 0x42, 0x49, 0x42, 0x67, 0x4e,
  0x56, 0x48, 0x53, 0x4d, 0x45, 0x51, 0x54, 0x41, 0x2f, 0x67, 0x42, 0x53,
  0x78, 0x6b, 0x54, 0x48, 0x31, 0x77, 0x4d, 0x70, 0x6f, 0x6d, 0x37, 0x56,
  0x79, 0x65, 0x73, 0x64, 0x62, 0x0a, 0x7a, 0x70, 0x7a, 0x62, 0x54, 0x35,
  0x58, 0x74, 0x55, 0x71, 0x45, 0x63, 0x70, 0x42, 0x6f, 0x77, 0x47, 0x44,
  0x45, 0x57, 0x4d, 0x42, 0x51, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77,
  0x77, 0x4e, 0x62, 0x58, 0x46, 0x30, 0x64, 0x48, 0x4e, 0x6c, 0x63, 0x6e,
  0x5a, 0x6c, 0x63, 0x69, 0x42, 0x44, 0x51, 0x59, 0x49, 0x4a, 0x41, 0x4a,
  0x64, 0x34, 0x4c, 0x2f, 0x76, 0x6f, 0x4a, 0x36, 0x4d, 0x55, 0x0a, 0x4d,
  0x42, 0x4d, 0x47, 0x41, 0x31, 0x55, 0x64, 0x4a, 0x51, 0x51, 0x4d, 0x4d,
  0x41, 0x6f, 0x47, 0x43, 0x43, 0x73, 0x47, 0x41, 0x51, 0x55, 0x46, 0x42,
  0x77, 0x4d, 0x43, 0x4d, 0x41, 0x73, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44,
  0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x48, 0x67, 0x44, 0x41, 0x4e, 0x42,
  0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41,
  0x51, 0x73, 0x46, 0x0a, 0x41, 0x41, 0x4f, 0x43, 0x41, 0x51, 0x45, 0x41,
  0x44, 0x50, 0x47, 0x4e, 0x31, 0x62, 0x4c, 0x57, 0x45, 0x49, 0x35, 0x4a,
  0x35, 0x6d, 0x4d, 0x31, 0x61, 0x54, 0x4c, 0x64, 0x38, 0x63, 0x50, 0x76,
  0x49, 0x62, 0x4e, 0x4f, 0x72, 0x6c, 0x63, 0x4c, 0x36, 0x70, 0x64, 0x62,
  0x48, 0x63, 0x2b, 0x52, 0x69, 0x71, 0x42, 0x71, 0x33, 0x61, 0x64, 0x61,
  0x74, 0x56, 0x5a, 0x71, 0x2f, 0x38, 0x76, 0x62, 0x0a, 0x73, 0x50, 0x43,
  0x64, 0x71, 0x49, 0x7a, 0x30, 0x58, 0x47, 0x30, 0x37, 0x65, 0x50, 0x51,
  0x77, 0x59, 0x51, 0x7a, 0x64, 0x63, 0x4f, 0x77, 0x67, 0x64, 0x7a, 0x78,
  0x4a, 0x73, 0x76, 0x4e, 0x42, 0x47, 0x62, 0x77, 0x36, 0x47, 0x4a, 0x6d,
  0x36, 0x32, 0x6c, 0x70, 0x52, 0x42, 0x2b, 0x62, 0x41, 0x30, 0x76, 0x79,
  0x2b, 0x71, 0x67, 0x6e, 0x34, 0x32, 0x6c, 0x78, 0x32, 0x57, 0x56, 0x4b,
  0x4d, 0x0a, 0x66, 0x53, 0x68, 0x68, 0x43, 0x59, 0x61, 0x71, 0x59, 0x52,
  0x46, 0x5a, 0x72, 0x4a, 0x52, 0x66, 0x2b, 0x79, 0x58, 0x65, 0x61, 0x74,
  0x58, 0x74, 0x64, 0x4a, 0x4d, 0x69, 0x75, 0x5a, 0x6f, 0x64, 0x55, 0x52,
  0x36, 0x70, 0x32, 0x68, 0x35, 0x6b, 0x42, 0x52, 0x6c, 0x45, 0x34, 0x62,
  0x72, 0x6d, 0x73, 0x66, 0x5a, 0x71, 0x33, 0x44, 0x4e, 0x53, 0x34, 0x33,
  0x6e, 0x65, 0x2f, 0x72, 0x6f, 0x49, 0x0a, 0x31, 0x2f, 0x66, 0x76, 0x43,
  0x31, 0x45, 0x51, 0x6f, 0x79, 0x5a, 0x71, 0x2b, 0x6f, 0x44, 0x32, 0x4e,
  0x4a, 0x53, 0x2f, 0x38, 0x4f, 0x64, 0x58, 0x52, 0x58, 0x43, 0x36, 0x43,
  0x32, 0x56, 0x69, 0x6d, 0x51, 0x62, 0x4e, 0x69, 0x67, 0x75, 0x42, 0x71,
  0x73, 0x71, 0x35, 0x32, 0x36, 0x4d, 0x71, 0x31, 0x7a, 0x37, 0x57, 0x31,
  0x6f, 0x50, 0x7a, 0x66, 0x5a, 0x75, 0x61, 0x30, 0x61, 0x4c, 0x6e, 0x0a,
  0x64, 0x6f, 0x53, 0x63, 0x67, 0x44, 0x52, 0x4a, 0x69, 0x65, 0x37, 0x65,
  0x69, 0x77, 0x52, 0x33, 0x74, 0x46, 0x66, 0x49, 0x66, 0x74, 0x32, 0x4a,
  0x4a, 0x44, 0x55, 0x6e, 0x6d, 0x55, 0x6c, 0x57, 0x39, 0x46, 0x2b, 0x54,
  0x74, 0x55, 0x48, 0x6d, 0x73, 0x76, 0x78, 0x4e, 0x50, 0x30, 0x58, 0x31,
  0x57, 0x68, 0x53, 0x36, 0x36, 0x70, 0x66, 0x64, 0x43, 0x45, 0x61, 0x6a,
  0x47, 0x59, 0x6c, 0x42, 0x0a, 0x6b, 0x33, 0x78, 0x57, 0x4b, 0x74, 0x6f,
  0x32, 0x78, 0x4c, 0x45, 0x65, 0x69, 0x71, 0x71, 0x72, 0x31, 0x32, 0x64,
  0x39, 0x64, 0x66, 0x34, 0x52, 0x52, 0x2b, 0x2b, 0x52, 0x6f, 0x77, 0x3d,
  0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43,
  0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
  0x2d, 0x2d, 0x2d, 0x0a, 0x00
};

uint8 espclient1_key[] = {
  0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50,
  0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d,
  0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x45, 0x76, 0x67, 0x49, 0x42,
  0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47,
  0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43,
  0x42, 0x4b, 0x67, 0x77, 0x67, 0x67, 0x53, 0x6b, 0x41, 0x67, 0x45, 0x41,
  0x41, 0x6f, 0x49, 0x42, 0x41, 0x51, 0x44, 0x6e, 0x66, 0x52, 0x33, 0x44,
  0x4e, 0x6b, 0x72, 0x4f, 0x69, 0x79, 0x76, 0x6f, 0x0a, 0x51, 0x4f, 0x44,
  0x6a, 0x41, 0x6e, 0x78, 0x70, 0x67, 0x59, 0x52, 0x31, 0x72, 0x4b, 0x6d,
  0x4c, 0x43, 0x70, 0x2f, 0x39, 0x42, 0x4f, 0x73, 0x6e, 0x51, 0x69, 0x77,
  0x73, 0x52, 0x6c, 0x71, 0x61, 0x31, 0x37, 0x33, 0x63, 0x66, 0x43, 0x51,
  0x64, 0x55, 0x6a, 0x2b, 0x65, 0x49, 0x46, 0x4e, 0x46, 0x68, 0x72, 0x53,
  0x66, 0x66, 0x2b, 0x31, 0x67, 0x4c, 0x68, 0x63, 0x4f, 0x58, 0x31, 0x55,
  0x47, 0x0a, 0x73, 0x2f, 0x78, 0x68, 0x78, 0x79, 0x54, 0x59, 0x33, 0x50,
  0x67, 0x33, 0x51, 0x79, 0x77, 0x6e, 0x49, 0x44, 0x42, 0x61, 0x36, 0x39,
  0x64, 0x2b, 0x34, 0x73, 0x38, 0x58, 0x77, 0x4d, 0x77, 0x77, 0x68, 0x66,
  0x72, 0x2b, 0x48, 0x6b, 0x73, 0x54, 0x41, 0x51, 0x53, 0x51, 0x54, 0x36,
  0x65, 0x70, 0x57, 0x64, 0x77, 0x68, 0x33, 0x52, 0x68, 0x56, 0x2f, 0x33,
  0x39, 0x41, 0x61, 0x4a, 0x65, 0x4b, 0x0a, 0x39, 0x72, 0x4d, 0x66, 0x62,
  0x70, 0x71, 0x74, 0x59, 0x61, 0x53, 0x42, 0x6e, 0x43, 0x50, 0x44, 0x34,
  0x69, 0x55, 0x55, 0x78, 0x58, 0x34, 0x6c, 0x4c, 0x2b, 0x5a, 0x32, 0x36,
  0x45, 0x71, 0x57, 0x4d, 0x46, 0x69, 0x68, 0x46, 0x48, 0x59, 0x48, 0x6a,
  0x55, 0x56, 0x52, 0x4e, 0x42, 0x58, 0x52, 0x47, 0x74, 0x79, 0x67, 0x47,
  0x39, 0x6a, 0x63, 0x33, 0x64, 0x71, 0x4b, 0x50, 0x76, 0x6c, 0x4f, 0x0a,
  0x44, 0x75, 0x79, 0x6b, 0x6f, 0x6b, 0x75, 0x56, 0x75, 0x6d, 0x34, 0x44,
  0x35, 0x38, 0x78, 0x7a, 0x48, 0x58, 0x58, 0x55, 0x7a, 0x50, 0x46, 0x6e,
  0x58, 0x66, 0x63, 0x2b, 0x55, 0x4a, 0x67, 0x76, 0x76, 0x57, 0x57, 0x53,
  0x50, 0x46, 0x6e, 0x67, 0x65, 0x52, 0x4e, 0x32, 0x67, 0x30, 0x57, 0x43,
  0x34, 0x50, 0x76, 0x52, 0x39, 0x33, 0x55, 0x67, 0x2b, 0x47, 0x42, 0x36,
  0x79, 0x42, 0x38, 0x69, 0x0a, 0x79, 0x71, 0x50, 0x61, 0x6b, 0x59, 0x5a,
  0x6e, 0x50, 0x71, 0x55, 0x79, 0x5a, 0x74, 0x77, 0x6c, 0x55, 0x36, 0x58,
  0x58, 0x2f, 0x30, 0x52, 0x35, 0x4f, 0x6f, 0x4a, 0x4e, 0x49, 0x70, 0x51,
  0x6b, 0x76, 0x6b, 0x4d, 0x46, 0x55, 0x4e, 0x56, 0x78, 0x49, 0x68, 0x49,
  0x62, 0x4d, 0x39, 0x4e, 0x67, 0x36, 0x43, 0x63, 0x48, 0x69, 0x66, 0x71,
  0x6b, 0x38, 0x72, 0x68, 0x61, 0x74, 0x31, 0x4f, 0x42, 0x0a, 0x48, 0x64,
  0x32, 0x57, 0x54, 0x37, 0x32, 0x6e, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41,
  0x45, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4b, 0x31, 0x70, 0x6e, 0x67,
  0x30, 0x71, 0x4d, 0x39, 0x6f, 0x4d, 0x69, 0x65, 0x54, 0x67, 0x44, 0x56,
  0x67, 0x68, 0x2b, 0x5a, 0x39, 0x30, 0x42, 0x67, 0x32, 0x39, 0x50, 0x66,
  0x6c, 0x4b, 0x43, 0x56, 0x59, 0x62, 0x42, 0x43, 0x6f, 0x52, 0x75, 0x56,
  0x4f, 0x6c, 0x0a, 0x6c, 0x4b, 0x52, 0x67, 0x72, 0x2f, 0x74, 0x6e, 0x43,
  0x41, 0x72, 0x72, 0x48, 0x58, 0x74, 0x51, 0x6a, 0x66, 0x45, 0x4d, 0x6d,
  0x32, 0x7a, 0x4e, 0x41, 0x62, 0x39, 0x47, 0x5a, 0x38, 0x45, 0x39, 0x69,
  0x30, 0x32, 0x4e, 0x4d, 0x61, 0x6a, 0x78, 0x37, 0x56, 0x6d, 0x45, 0x46,
  0x33, 0x49, 0x57, 0x6f, 0x52, 0x48, 0x69, 0x58, 0x44, 0x63, 0x51, 0x62,
  0x41, 0x76, 0x43, 0x7a, 0x77, 0x37, 0x6c, 0x0a, 0x51, 0x46, 0x47, 0x74,
  0x58, 0x4c, 0x78, 0x58, 0x5a, 0x7a, 0x67, 0x69, 0x55, 0x41, 0x2f, 0x6e,
  0x6a, 0x42, 0x73, 0x69, 0x6c, 0x50, 0x54, 0x4e, 0x55, 0x7a, 0x6a, 0x42,
  0x51, 0x4d, 0x75, 0x34, 0x54, 0x71, 0x59, 0x73, 0x62, 0x7a, 0x31, 0x42,
  0x74, 0x78, 0x2f, 0x68, 0x67, 0x4d, 0x49, 0x54, 0x66, 0x50, 0x74, 0x32,
  0x41, 0x76, 0x39, 0x50, 0x66, 0x31, 0x4e, 0x4f, 0x55, 0x65, 0x43, 0x4b,
  0x0a, 0x63, 0x4a, 0x52, 0x36, 0x39, 0x47, 0x30, 0x65, 0x4c, 0x56, 0x47,
  0x49, 0x6d, 0x42, 0x56, 0x68, 0x4a, 0x6d, 0x4a, 0x78, 0x4c, 0x4d, 0x34,
  0x65, 0x35, 0x6c, 0x77, 0x73, 0x33, 0x52, 0x2b, 0x73, 0x59, 0x2f, 0x6f,
  0x36, 0x55, 0x6f, 0x72, 0x34, 0x48, 0x30, 0x30, 0x47, 0x43, 0x36, 0x65,
  0x66, 0x4e, 0x73, 0x5a, 0x49, 0x79, 0x4b, 0x59, 0x44, 0x42, 0x56, 0x5a,
  0x75, 0x48, 0x45, 0x47, 0x76, 0x0a, 0x6b, 0x4d, 0x55, 0x34, 0x41, 0x57,
  0x5a, 0x46, 0x48, 0x62, 0x43, 0x4f, 0x2f, 0x65, 0x48, 0x75, 0x38, 0x34,
  0x70, 0x63, 0x6e, 0x6a, 0x33, 0x4b, 0x58, 0x5a, 0x75, 0x55, 0x31, 0x6e,
  0x6c, 0x4a, 0x53, 0x6f, 0x71, 0x66, 0x66, 0x4f, 0x6e, 0x70, 0x32, 0x58,
  0x74, 0x55, 0x59, 0x58, 0x74, 0x72, 0x2b, 0x2b, 0x63, 0x7a, 0x48, 0x2f,
  0x59, 0x71, 0x59, 0x63, 0x2f, 0x4e, 0x68, 0x6f, 0x4f, 0x59, 0x0a, 0x44,
  0x70, 0x58, 0x59, 0x46, 0x4f, 0x6a, 0x39, 0x7a, 0x7a, 0x59, 0x58, 0x41,
  0x71, 0x45, 0x6e, 0x32, 0x65, 0x4a, 0x58, 0x46, 0x56, 0x65, 0x77, 0x72,
  0x76, 0x63, 0x52, 0x37, 0x69, 0x52, 0x76, 0x66, 0x43, 0x4a, 0x4b, 0x64,
  0x43, 0x31, 0x6b, 0x69, 0x50, 0x6b, 0x43, 0x67, 0x59, 0x45, 0x41, 0x2f,
  0x70, 0x79, 0x55, 0x66, 0x66, 0x30, 0x32, 0x67, 0x64, 0x6a, 0x66, 0x45,
  0x63, 0x55, 0x75, 0x0a, 0x74, 0x65, 0x51, 0x53, 0x63, 0x67, 0x31, 0x66,
  0x6d, 0x79, 0x55, 0x30, 0x4c, 0x38, 0x2f, 0x76, 0x55, 0x51, 0x2f, 0x4c,
  0x73, 0x39, 0x57, 0x77, 0x6a, 0x76, 0x4a, 0x4c, 0x50, 0x70, 0x31, 0x63,
  0x44, 0x6e, 0x33, 0x43, 0x52, 0x64, 0x46, 0x31, 0x42, 0x7a, 0x6c, 0x2f,
  0x34, 0x66, 0x65, 0x54, 0x48, 0x52, 0x73, 0x50, 0x64, 0x48, 0x45, 0x51,
  0x50, 0x50, 0x70, 0x63, 0x63, 0x6d, 0x78, 0x59, 0x0a, 0x48, 0x44, 0x47,
  0x37, 0x45, 0x59, 0x4e, 0x6e, 0x35, 0x38, 0x72, 0x6d, 0x70, 0x69, 0x79,
  0x76, 0x6e, 0x2f, 0x30, 0x32, 0x2b, 0x68, 0x46, 0x63, 0x78, 0x4f, 0x76,
  0x78, 0x55, 0x42, 0x36, 0x6d, 0x58, 0x78, 0x4b, 0x4c, 0x51, 0x62, 0x6e,
  0x79, 0x45, 0x76, 0x4a, 0x32, 0x72, 0x64, 0x72, 0x69, 0x4a, 0x56, 0x66,
  0x6d, 0x58, 0x61, 0x7a, 0x49, 0x75, 0x6a, 0x39, 0x4b, 0x4a, 0x48, 0x36,
  0x72, 0x0a, 0x38, 0x59, 0x34, 0x2f, 0x48, 0x68, 0x4d, 0x44, 0x76, 0x6d,
  0x61, 0x34, 0x54, 0x76, 0x4f, 0x47, 0x71, 0x53, 0x67, 0x50, 0x55, 0x4b,
  0x56, 0x70, 0x32, 0x41, 0x73, 0x43, 0x67, 0x59, 0x45, 0x41, 0x36, 0x4d,
  0x42, 0x43, 0x48, 0x58, 0x54, 0x77, 0x6a, 0x52, 0x38, 0x6a, 0x43, 0x57,
  0x6a, 0x68, 0x54, 0x44, 0x4a, 0x69, 0x37, 0x52, 0x30, 0x59, 0x59, 0x47,
  0x33, 0x65, 0x49, 0x4a, 0x48, 0x70, 0x0a, 0x70, 0x52, 0x63, 0x72, 0x4e,
  0x31, 0x49, 0x64, 0x48, 0x39, 0x4e, 0x61, 0x53, 0x45, 0x70, 0x67, 0x34,
  0x31, 0x2f, 0x4d, 0x74, 0x63, 0x34, 0x41, 0x68, 0x52, 0x6e, 0x73, 0x35,
  0x68, 0x65, 0x72, 0x76, 0x6f, 0x70, 0x54, 0x31, 0x59, 0x33, 0x7a, 0x75,
  0x44, 0x58, 0x38, 0x78, 0x46, 0x4e, 0x70, 0x49, 0x47, 0x6f, 0x57, 0x63,
  0x4f, 0x69, 0x6b, 0x66, 0x46, 0x70, 0x75, 0x62, 0x63, 0x43, 0x4a, 0x0a,
  0x63, 0x35, 0x4f, 0x57, 0x38, 0x32, 0x45, 0x76, 0x68, 0x68, 0x46, 0x73,
  0x76, 0x2f, 0x30, 0x57, 0x65, 0x4e, 0x56, 0x48, 0x62, 0x5a, 0x33, 0x52,
  0x56, 0x52, 0x35, 0x72, 0x45, 0x61, 0x78, 0x45, 0x35, 0x54, 0x67, 0x68,
  0x68, 0x6a, 0x4c, 0x61, 0x6f, 0x4d, 0x47, 0x67, 0x2f, 0x46, 0x64, 0x5a,
  0x58, 0x71, 0x44, 0x4b, 0x52, 0x65, 0x6d, 0x57, 0x39, 0x46, 0x55, 0x31,
  0x58, 0x35, 0x2f, 0x4d, 0x0a, 0x6f, 0x6f, 0x38, 0x4c, 0x49, 0x4b, 0x4a,
  0x49, 0x52, 0x6c, 0x55, 0x43, 0x67, 0x59, 0x45, 0x41, 0x33, 0x53, 0x39,
  0x66, 0x58, 0x48, 0x66, 0x74, 0x73, 0x79, 0x32, 0x59, 0x30, 0x39, 0x49,
  0x74, 0x65, 0x76, 0x77, 0x50, 0x2f, 0x68, 0x36, 0x61, 0x45, 0x4b, 0x68,
  0x6f, 0x52, 0x71, 0x54, 0x6e, 0x37, 0x4d, 0x37, 0x42, 0x45, 0x70, 0x41,
  0x76, 0x32, 0x6d, 0x36, 0x6f, 0x61, 0x56, 0x50, 0x41, 0x0a, 0x6c, 0x69,
  0x49, 0x76, 0x39, 0x41, 0x45, 0x37, 0x48, 0x6a, 0x53, 0x59, 0x59, 0x4e,
  0x42, 0x33, 0x62, 0x39, 0x43, 0x44, 0x51, 0x34, 0x2b, 0x35, 0x49, 0x4a,
  0x41, 0x4b, 0x59, 0x61, 0x69, 0x33, 0x66, 0x6e, 0x37, 0x42, 0x57, 0x54,
  0x79, 0x44, 0x74, 0x6e, 0x79, 0x77, 0x6c, 0x47, 0x6d, 0x37, 0x68, 0x45,
  0x77, 0x77, 0x52, 0x31, 0x74, 0x76, 0x38, 0x4f, 0x35, 0x62, 0x61, 0x31,
  0x50, 0x46, 0x0a, 0x43, 0x6c, 0x43, 0x4d, 0x77, 0x32, 0x4e, 0x71, 0x35,
  0x59, 0x54, 0x58, 0x44, 0x72, 0x39, 0x59, 0x75, 0x45, 0x49, 0x39, 0x4d,
  0x4f, 0x47, 0x61, 0x57, 0x78, 0x6f, 0x43, 0x4b, 0x65, 0x51, 0x56, 0x4d,
  0x54, 0x70, 0x32, 0x6f, 0x49, 0x53, 0x36, 0x4f, 0x74, 0x7a, 0x33, 0x66,
  0x6a, 0x62, 0x57, 0x6f, 0x2f, 0x72, 0x57, 0x47, 0x79, 0x51, 0x6e, 0x35,
  0x2f, 0x4d, 0x43, 0x67, 0x59, 0x42, 0x2b, 0x0a, 0x33, 0x56, 0x79, 0x73,
  0x52, 0x62, 0x4e, 0x67, 0x6d, 0x4a, 0x6f, 0x32, 0x5a, 0x4d, 0x35, 0x35,
  0x41, 0x2f, 0x58, 0x63, 0x48, 0x4d, 0x48, 0x4f, 0x76, 0x64, 0x51, 0x58,
  0x6d, 0x4c, 0x44, 0x72, 0x35, 0x61, 0x63, 0x4f, 0x72, 0x6c, 0x6c, 0x6c,
  0x6f, 0x59, 0x52, 0x53, 0x5a, 0x77, 0x68, 0x4d, 0x70, 0x30, 0x6b, 0x6a,
  0x78, 0x37, 0x65, 0x4d, 0x31, 0x55, 0x62, 0x46, 0x58, 0x42, 0x32, 0x6d,
  0x0a, 0x37, 0x43, 0x73, 0x70, 0x2b, 0x67, 0x66, 0x67, 0x58, 0x72, 0x7a,
  0x36, 0x48, 0x69, 0x54, 0x74, 0x49, 0x43, 0x59, 0x2f, 0x51, 0x4f, 0x39,
  0x33, 0x51, 0x4b, 0x74, 0x30, 0x63, 0x7a, 0x2f, 0x34, 0x6d, 0x58, 0x66,
  0x73, 0x44, 0x51, 0x73, 0x6b, 0x58, 0x70, 0x63, 0x53, 0x52, 0x74, 0x64,
  0x61, 0x34, 0x5a, 0x58, 0x66, 0x62, 0x2b, 0x68, 0x4d, 0x4a, 0x78, 0x70,
  0x68, 0x4e, 0x61, 0x38, 0x50, 0x0a, 0x36, 0x66, 0x71, 0x4c, 0x39, 0x57,
  0x67, 0x70, 0x75, 0x36, 0x45, 0x4f, 0x4b, 0x6d, 0x5a, 0x79, 0x4a, 0x39,
  0x35, 0x5a, 0x49, 0x53, 0x76, 0x41, 0x33, 0x6a, 0x6b, 0x4c, 0x65, 0x45,
  0x54, 0x49, 0x54, 0x6f, 0x50, 0x59, 0x4d, 0x39, 0x79, 0x46, 0x53, 0x51,
  0x4b, 0x42, 0x67, 0x45, 0x57, 0x48, 0x4c, 0x4b, 0x2f, 0x5a, 0x57, 0x5a,
  0x37, 0x47, 0x6d, 0x4a, 0x39, 0x4d, 0x4d, 0x34, 0x48, 0x5a, 0x0a, 0x38,
  0x36, 0x33, 0x31, 0x63, 0x70, 0x45, 0x6f, 0x72, 0x62, 0x4a, 0x71, 0x58,
  0x33, 0x7a, 0x4f, 0x58, 0x6f, 0x47, 0x34, 0x58, 0x48, 0x45, 0x69, 0x34,
  0x51, 0x62, 0x62, 0x57, 0x51, 0x43, 0x77, 0x4a, 0x4b, 0x4a, 0x68, 0x34,
  0x79, 0x33, 0x37, 0x6d, 0x31, 0x31, 0x33, 0x4c, 0x66, 0x71, 0x32, 0x36,
  0x65, 0x72, 0x35, 0x75, 0x38, 0x61, 0x68, 0x37, 0x79, 0x45, 0x30, 0x62,
  0x4f, 0x34, 0x47, 0x0a, 0x66, 0x57, 0x37, 0x37, 0x6b, 0x54, 0x73, 0x44,
  0x44, 0x68, 0x72, 0x61, 0x37, 0x58, 0x55, 0x36, 0x6b, 0x51, 0x57, 0x76,
  0x41, 0x4a, 0x5a, 0x71, 0x63, 0x45, 0x36, 0x57, 0x44, 0x51, 0x75, 0x32,
  0x41, 0x77, 0x61, 0x38, 0x62, 0x47, 0x6f, 0x32, 0x33, 0x2f, 0x54, 0x34,
  0x38, 0x77, 0x48, 0x47, 0x66, 0x58, 0x74, 0x57, 0x4d, 0x43, 0x2b, 0x43,
  0x54, 0x63, 0x2b, 0x68, 0x2f, 0x31, 0x73, 0x54, 0x0a, 0x33, 0x47, 0x53,
  0x6e, 0x7a, 0x77, 0x55, 0x76, 0x52, 0x77, 0x31, 0x52, 0x2f, 0x46, 0x53,
  0x43, 0x4c, 0x47, 0x76, 0x75, 0x53, 0x52, 0x38, 0x70, 0x0a, 0x2d, 0x2d,
  0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41,
  0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x00
};

// *****************************
//const char* ssid = WIFI_SSID;
//const char* password = WIFI_PASSWORD;


const char* ssid = "freeradius-2G";
const char* password = "any_password_not_used";

const char* otapassword = OTA_PASSWORD;

const char* mqttuser = MQTT_TEST_USER;
const char* mqttpass = MQTT_TEST_PASS;

IPAddress mqtt_server = MQTT_TEST_SERVER;
const char* fingerprint = "70 B2 BF 0D 4E 2A 54 FC DD C3 75 03 CD 42 20 71 9C 4A 97 37";
//connecting to 192.168.10.144
//certificate matches

// test
//const char* fingerprint = "70 B2 BF 0D 4E 2A 54 FC DD C3 75 03 CD 42 20 71 9C 4A 97 36";
//connecting to 192.168.10.144
//certificate doesn't match
//-------------------------------
char* topic = "pubtest";

String clientName;

long lastReconnectAttempt = 0;
long lastMsg = 0;
int test_para = 2000;
unsigned long startMills;

//------------------------------
WiFiClientSecure wifiClient;
//WiFiClient wifiClient;
PubSubClient client(mqtt_server, 8883, wifiClient);

//----------------------
String macToStr(const uint8_t* mac);
void sendmqttMsg(char* topictosend, String payload);


void verifytls() {
  // Use WiFiClientSecure class to create TLS connection
  Serial.print("connecting to ");
  Serial.println(mqtt_server);
  if (!wifiClient.connect(mqtt_server, 8883)) {
    Serial.println("connection failed");
    return;
  }

  if (wifiClient.verify(fingerprint, mqtt_server.toString().c_str())) {
    Serial.println("certificate matches");
  } else {
    Serial.println("certificate doesn't match");
  }
}


//-----------------------
boolean reconnect()
{
  if (!client.connected()) {
    if (client.connect((char*) clientName.c_str(), mqttuser, mqttpass)) {
      if (DEBUG_PRINT) {
        Serial.println("===> mqtt connected");
      }
    } else {
      if (DEBUG_PRINT) {
        Serial.print("---> mqtt failed, rc=");
        Serial.println(client.state());
      }
    }
  }
  return client.connected();
}

void wifi_connect()
{
  if (WiFi.status() != WL_CONNECTED) {
    // WIFI
    if (DEBUG_PRINT) {
      Serial.println();
      Serial.print("===> WIFI ---> Connecting to ");
      Serial.println(ssid);
    }
    delay(10);
    Serial.println("Cert set up");
    wifi_station_set_cert_key(espclient1_crt, sizeof(espclient1_crt), espclient1_key, sizeof(espclient1_key), NULL, 0);
    Serial.println("Cert set done");
    Serial.println("");
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);

    int Attempt = 0;
    while (WiFi.status() != WL_CONNECTED) {
      if (DEBUG_PRINT) {
        Serial.print(". ");
        Serial.print(Attempt);
      }
      delay(100);
      Attempt++;
      if (Attempt == 150)
      {
        if (DEBUG_PRINT) {
          Serial.println();
          Serial.println("-----> Could not connect to WIFI");
        }
        ESP.restart();
        delay(200);
      }

    }

    wifi_station_clear_cert_key();
    if (DEBUG_PRINT) {
      Serial.println();
      Serial.print("===> WiFi connected");
      Serial.print(" ------> IP address: ");
      Serial.println(WiFi.localIP());
    }
  }
}

void setup()
{
  startMills = millis();

  if (DEBUG_PRINT) {
    Serial.begin(115200);
  }

  wifi_connect();

  clientName += "esp8266-";
  uint8_t mac[6];
  WiFi.macAddress(mac);
  clientName += macToStr(mac);
  clientName += "-";
  clientName += String(micros() & 0xff, 16);

  Serial.println(clientName);

  verifytls();

  //OTA
  // Port defaults to 8266
  //ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("esp-test");


  // No authentication by default
  ArduinoOTA.setPassword(otapassword);

  ArduinoOTA.onStart([]() {
    //Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    //Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    //Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    ESP.restart();
    /*
      if (error == OTA_AUTH_ERROR) abort();
      else if (error == OTA_BEGIN_ERROR) abort();
      else if (error == OTA_CONNECT_ERROR) abort();
      else if (error == OTA_RECEIVE_ERROR) abort();
      else if (error == OTA_END_ERROR) abort();
    */
  });

  ArduinoOTA.begin();
}

void loop()
{
  if (WiFi.status() == WL_CONNECTED) {
    if (!client.connected()) {
      long now = millis();
      if (now - lastReconnectAttempt > 2000) {
        lastReconnectAttempt = now;
        if (reconnect()) {
          lastReconnectAttempt = 0;
        }
      }
    } else {
      long now = millis();
      if (now - lastMsg > test_para) {
        lastMsg = now;
        String payload = "{\"startMills\":";
        payload += (millis() - startMills);
        payload += ",\"FreeHeap\":";
        payload += ESP.getFreeHeap();
        payload += ",\"RSSI\":";
        payload += WiFi.RSSI();
        payload += "}";
        sendmqttMsg(topic, payload);
      }
      client.loop();
      ArduinoOTA.handle();
    }
  } else {
    wifi_connect();
  }

}

void sendmqttMsg(char* topictosend, String payload)
{

  if (client.connected()) {
    if (DEBUG_PRINT) {
      Serial.print("Sending payload: ");
      Serial.print(payload);
    }

    unsigned int msg_length = payload.length();

    if (DEBUG_PRINT) {
      Serial.print(" length: ");
      Serial.println(msg_length);
    }

    byte* p = (byte*)malloc(msg_length);
    memcpy(p, (char*) payload.c_str(), msg_length);

    if ( client.publish(topictosend, p, msg_length)) {
      if (DEBUG_PRINT) {
        Serial.println("Publish ok");
      }
      free(p);
      //return 1;
    } else {
      if (DEBUG_PRINT) {
        Serial.println("Publish failed");
      }
      free(p);
      //return 0;
    }
  }
}

String macToStr(const uint8_t* mac)
{
  String result;
  for (int i = 0; i < 6; ++i) {
    result += String(mac[i], 16);
    if (i < 5)
      result += ':';
  }
  return result;
}
